﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using MySql.Data.MySqlClient;
using Microsoft.Win32;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Configuration;

namespace MySqlQueryTool
{
    /*
     * Good luck!
     * */

    class Program
    {
        private static RegistryKey appKey;
        private static string _connectionString;
        private static string _database;
        private static MySqlConnection _conn = null;
        private static string _path = "";

        [STAThread]
        static void Main(string[] args)
        {
            PrintSplash();

            try
            {
                using (TcpClient mysqlClient = new TcpClient("localhost", 3308))
                {
                    if (mysqlClient.Connected)
                    {
                        byte[] buff = new byte[40];
                        NetworkStream ns = mysqlClient.GetStream();
                        ns.Read(buff, 0, buff.Length);

                        byte[] version = new byte[7];
                        Array.Copy(buff, 5, version, 0, 7);
                        WriteMessage("> MySql Server: " + System.Text.Encoding.ASCII.GetString(version) + "detected on localhost on port 3308");
                    }
                }
            }
            catch (Exception e){
                WriteError("> MySql server was not found on localhost on port 3306");
            }

            RegistryKey softwareKey = Registry.CurrentUser.OpenSubKey("Software", true);
            appKey = softwareKey.OpenSubKey("MySqlQueryTool", true);

            if (appKey == null)
            {
                appKey = softwareKey.CreateSubKey("MySqlQueryTool", RegistryKeyPermissionCheck.ReadWriteSubTree);
                appKey.SetValue("connection_string", "");
                appKey.SetValue("path", "");
            }
            else
            {
                string connectionString = ConfigurationManager.AppSettings["connMySql"].ToString(); //"Data Source=localhost;port=3308;Initial Catalog=new_schema1;User Id=root;password=admin"; //appKey.GetValue("connection_string","").ToString();

                if (connectionString != "")
                {
                    _path = appKey.GetValue("path").ToString();
                    Connect(new string[] { connectionString });
                }
            }

            while (true)
            {
                if (string.IsNullOrEmpty(_database))
                {
                    Console.Write("> ");
                }
                else
                {
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.Write("[");
                    Console.ForegroundColor = ConsoleColor.Cyan;
                    Console.Write(_database);
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.Write("]");
                    Console.ForegroundColor = ConsoleColor.Gray;
                    Console.Write("> ");
                }

                string cmd = Console.ReadLine();

                if (!string.IsNullOrEmpty(cmd))
                {
                    string[] segments = ParseCommand(cmd);
                    string currentCmd = segments[0];
                    segments = segments.Where(x => x != currentCmd && x !="").ToArray();

                    switch (currentCmd)
                    {
                        case "connect":
                            Connect(segments);
                            break;
                        case "disconnect":
                            Disconnect();
                            break;
                        case "db":
                            Datebase(segments);
                            break;
                        case "set":
                            Set(segments);
                            break;
                        case "get":
                            Get(segments);
                            break;
                        case "show":
                            Show(segments);
                            break;
                        case "describe":
                            Describe(segments);
                            break;
                        case "export":
                            Export(segments);
                            break;
                        case "generate":
                            Generate(segments);
                            break;
                        case "clear":
                            Clear();
                            break;
                        case "clean":
                            Clean();
                            break;
                        case "help":
                            Help();
                            break;
                        default:
                            WriteError(currentCmd + " is not a supported command.");
                            break;

                    }

                }
            }
        }

        public static void Set(string[] cmdSegments)
        {
            if (cmdSegments.Length == 2)
            {
                string paramName = cmdSegments[0];
                string paramValue = cmdSegments[1];

                RegistryKey softwareKey = Registry.CurrentUser.OpenSubKey("Software", true);
                appKey = softwareKey.OpenSubKey("MySqlQueryTool", true);

                if (appKey != null)
                {
                    appKey = softwareKey.CreateSubKey("MySqlQueryTool", RegistryKeyPermissionCheck.ReadWriteSubTree);
                    appKey.SetValue(paramName, paramValue);
                }
            }
        }

        public static void Get(string[] cmdSegments)
        {
            if (cmdSegments.Length == 1)
            {
                string paramName = cmdSegments[0];

                RegistryKey softwareKey = Registry.CurrentUser.OpenSubKey("Software", true);
                appKey = softwareKey.OpenSubKey("MySqlQueryTool", true);

                if (appKey != null)
                {
                    appKey = softwareKey.CreateSubKey("MySqlQueryTool", RegistryKeyPermissionCheck.ReadWriteSubTree);
                    WriteMessage(appKey.GetValue(paramName, "").ToString());
                }
            }
        }

        public static void Entity(string[] cmdSegments)
        {
            if (cmdSegments.Length == 3)
            {
                string entityName = cmdSegments[0];
                string tableName = cmdSegments[1];
                string programmingLanguage = cmdSegments[2];

                if (_conn != null)
                {
                    using (MySqlCommand mysqlCmd = new MySqlCommand("DESCRIBE " + tableName, _conn))
                    {
                        try
                        {
                            MySqlDataReader reader = mysqlCmd.ExecuteReader();

                            List<string> fields = new List<string>();
                            List<string> fieldDataTypes = new List<string>();

                            while (reader.Read())
                            {
                                fields.Add(reader[0].ToString());
                                string dType = reader[1].ToString();

                                int chPos = dType.IndexOf('(');
                                if (chPos > -1)
                                {
                                    dType = dType.Substring(0, chPos);
                                }

                                fieldDataTypes.Add(dType);
                            }
                            reader.Close();

                            StringBuilder entityClass = new StringBuilder();
                            string fileExtension = "";

                            switch (programmingLanguage)
                            {
                                case "php":
                                    entityClass.AppendLine("<?php");
                                    entityClass.AppendLine();

                                    entityClass.AppendLine("class " + entityName + "{");

                                    foreach (string field in fields)
                                    {
                                        entityClass.AppendLine(string.Format("\tprotected ${0};", field));
                                    }

                                    foreach (string field in fields)
                                    {
                                        entityClass.AppendLine();
                                        entityClass.AppendLine("\tpublic function set" + CamelCaseString(field, true) + "($" + CamelCaseString(field, false) + "){");
                                        entityClass.AppendLine(string.Format("\t\t$this->{0} = ${1};", field, CamelCaseString(field, false)));
                                        entityClass.AppendLine("\t}");

                                        entityClass.AppendLine();
                                        entityClass.AppendLine("\tpublic function get" + CamelCaseString(field, true) + "(){");
                                        entityClass.AppendLine(string.Format("\t\treturn $this->{0};", field));
                                        entityClass.AppendLine("\t}");
                                    }

                                    entityClass.AppendLine("}");
                                    entityClass.AppendLine();
                                    entityClass.AppendLine("?>");
                                    fileExtension = "php";
                                    break;

                                case "cs":
                                    entityClass.AppendLine("using System;");
                                    entityClass.AppendLine();

                                    entityClass.AppendLine("public class " + entityName);
                                    entityClass.AppendLine("{");

                                    int idx = 0;
                                    foreach (string field in fields)
                                    {
                                        string dType = "";

                                        switch (fieldDataTypes[idx])
                                        {
                                            case "int":
                                            case "smallint":
                                            case "tinyint":
                                                dType = "int";
                                                break;
                                            case "bigint":
                                                dType = "long";
                                                break;
                                            case "double":
                                            case "decimal":
                                                dType = "double";
                                                break;
                                            case "varchar":
                                            case "text":
                                                dType = "string";
                                                break;
                                            case "timestamp":
                                            case "datetime":
                                                dType = "DateTime";
                                                break;
                                            case "bit":
                                                dType = "bool";
                                                break;
                                            default:
                                                dType = "object";
                                                break;

                                        }
                                        entityClass.AppendLine();
                                        entityClass.Append("\tpublic " + dType + " " + field);
                                        entityClass.Append(" { get; set; }");
                                        //entityClass.Append("set;");
                                        //entityClass.Append("\t\tget;");
                                        //entityClass.Append("\t}");
                                        ++idx;
                                    }
                                    entityClass.AppendLine("");
                                    entityClass.AppendLine("}");
                                    fileExtension = "cs";
                                    break;
                            }

                            if (fileExtension != "")
                            {
                                try
                                {
                                    string path = GetRegValue("path");
                                    string fileName = "";

                                    if (path != "")
                                    {
                                        fileName = path + "\\" + entityName + "." + fileExtension;
                                    }
                                    else
                                    {
                                        fileName = entityName + "." + fileExtension;
                                    }

                                    using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write))
                                    {
                                        StreamWriter sWriter = new StreamWriter(fs);
                                        sWriter.Write(entityClass);
                                        sWriter.Flush();
                                        sWriter.Close();

                                        WriteMessage("Entity " + entityName + " generated: " + fileName);
                                    }
                                }
                                catch (Exception ioe)
                                {
                                    WriteError(ioe.Message);
                                }
                            }
                            else
                            {
                                WriteError("Entity type " + programmingLanguage + " is not supported");
                            }
                        }
                        catch (Exception e)
                        {
                            WriteError(e.Message);
                        }
                    }
                }
                else
                {
                    WriteError("MySql connection is not open. Type help for usage.");
                }
            }
            else
            {
                WriteError("Incorrect number of arguments. Type help for usage"); 
            }
        }

        public static void Generate(string[] cmdSegments)
        {
            string currentCmd = cmdSegments[0];
            cmdSegments = cmdSegments.Where(x => x != currentCmd && x !="").ToArray();

            switch (currentCmd)
            {
                case "entity":
                    Entity(cmdSegments);
                    break;
                default:
                    WriteError(currentCmd + " is not a supported command.");
                    break;
            }
        }

        public static void Export(string[] cmdSegments)
        {
            if (cmdSegments.Length == 2)
            {
                if (_conn != null)
                {
                    string tableName = cmdSegments[0].Trim();
                    string exportPath = cmdSegments[1].Trim();
                    bool export = false;

                    if (exportPath.Substring(0, 1) == "$")
                    {
                        int chPos = exportPath.IndexOf('.');

                        if (chPos > -1)
                        {
                            string paramKey = exportPath.Substring(1, chPos - 1);
                            string file = exportPath.Substring(chPos + 1);

                            RegistryKey softwareKey = Registry.CurrentUser.OpenSubKey("Software", true);
                            appKey = softwareKey.OpenSubKey("MySqlQueryTool", true);

                            if (appKey != null)
                            {
                                try
                                {
                                    exportPath = appKey.GetValue(paramKey).ToString();
                                    exportPath += "\\" + file;
                                    export = true;
                                }
                                catch (Exception re)
                                {
                                    WriteError("Registry key not found: " + paramKey);
                                }
                            }
                        }
                    }
                    else
                    {
                        export = true;
                    }

                    if (tableName == "*")
                    {
                        try
                        {
                            using (MySqlCommand mysqlCmd = new MySqlCommand("SHOW TABLES", _conn))
                            {
                                MySqlDataReader reader = mysqlCmd.ExecuteReader();
                                List<string> tables = new List<string>();

                                while (reader.Read())
                                {
                                    tables.Add(reader.GetString(0));
                                }
                                reader.Close();

                                _Export(tables, exportPath);

                            }
                        }
                        catch (Exception e)
                        {
                            WriteError(e.Message);
                        }
                    }
                    else
                    {
                        if (export)
                        {
                            List<string> tables = tableName.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
                            _Export(tables, exportPath);
                        }
                    }
                }
                else
                {
                    WriteError("MySql connection is not open. Type help for usage.");
                }
            }
            else
            {
                WriteError("Incorrect number of arguments. Type help for usage"); 
            }
        }

        private static void _Export(List<string> tables, string exportPath)
        {
            try
            {
                using (FileStream fs = new FileStream(exportPath, FileMode.Create, FileAccess.Write))
                {
                    StreamWriter sWriter = new StreamWriter(fs);

                    sWriter.WriteLine("CREATE DATABASE  IF NOT EXISTS `" + _database + "`;");
                    sWriter.WriteLine("USE `" + _database + "`;");
                    sWriter.WriteLine();

                    foreach (string table in tables)
                    {
                        using (MySqlCommand tblCmd = new MySqlCommand("SHOW CREATE TABLE " + table, _conn))
                        {
                            MySqlDataReader tblReader = tblCmd.ExecuteReader();
                            tblReader.Read();
                            string statement = tblReader.GetString(1);

                            sWriter.WriteLine("--");
                            sWriter.WriteLine("-- Table structure for table `" + table + "`");
                            sWriter.WriteLine("--");
                            sWriter.WriteLine();
                            sWriter.WriteLine("DROP TABLE IF EXISTS `" + table + "`;");
                            sWriter.WriteLine();
                            sWriter.Write(statement + ";");
                            sWriter.WriteLine();
                            sWriter.WriteLine();
                            tblReader.Close();

                            using (MySqlCommand tblDataCmd = new MySqlCommand("SELECT * FROM " + table, _conn))
                            {
                                MySqlDataReader tblDataReader = tblDataCmd.ExecuteReader();

                                sWriter.WriteLine();
                                sWriter.WriteLine("--");
                                sWriter.WriteLine("-- Table data for table `" + table + "`");
                                sWriter.WriteLine("--");
                                sWriter.WriteLine();


                                string sqlInsert = "INSERT INTO `" + table + "` VALUES ";
                                int rowCount = 0;

                                while (tblDataReader.Read())
                                {
                                    sqlInsert += "(";

                                    int fieldCount = tblDataReader.FieldCount;

                                    for (int i = 0; i < fieldCount; i++)
                                    {
                                        string value = "";

                                        if (tblDataReader.GetFieldType(i) == typeof(System.UInt16) ||
                                            tblDataReader.GetFieldType(i) == typeof(System.UInt32) ||
                                            tblDataReader.GetFieldType(i) == typeof(System.UInt64) ||
                                            tblDataReader.GetFieldType(i) == typeof(System.Decimal) ||
                                            tblDataReader.GetFieldType(i) == typeof(float))
                                        {

                                            if (DBNull.Value == tblDataReader[i])
                                            {
                                                value = "NULL,";
                                            }
                                            else
                                            {
                                                value = string.Format("{0},", tblDataReader[i]);
                                            }
                                        }
                                        else if (tblDataReader.GetFieldType(i) == typeof(DateTime))
                                        {
                                            try
                                            {
                                                DateTime dateTime = (DateTime)tblDataReader[i];
                                                value = "'" + dateTime.ToString("yyyy-MM-dd HH':'mm':'ss") + "',";
                                            }
                                            catch (Exception eDt)
                                            {
                                                value = "Null,";
                                            }
                                        }
                                        else if (DBNull.Value == tblDataReader[i])
                                        {
                                            value = "NULL,";
                                        }
                                        else
                                        {
                                            value = string.Format("'{0}',", tblDataReader[i].ToString().Replace("'", "\\'").Replace("\"", "\\\""));
                                        }

                                        if (i == (fieldCount - 1))
                                        {
                                            value = value.Trim(new char[] { ',' });
                                        }

                                        sqlInsert += value;
                                    }

                                    sqlInsert += "),";
                                    ++rowCount;
                                }

                                if (rowCount > 0)
                                {
                                    sqlInsert = sqlInsert.Trim(new char[] { ',' }) + ";";


                                    sWriter.WriteLine(sqlInsert);
                                    sWriter.WriteLine();
                                }
                                tblDataReader.Close();
                            }
                        }
                    }

                    sWriter.Flush();
                    sWriter.Close();

                    WriteMessage("Exported to " + exportPath);
                }
            }
            catch (Exception e)
            {
                WriteError(e.Message);
            }

        }

        public static void Table(string[] cmdSegments)
        {
            if (cmdSegments.Length == 1)
            {
                string tableName = cmdSegments[0];

                if (_conn != null)
                {
                    try
                    {
                        using (MySqlCommand mysqlCmd = new MySqlCommand("DESCRIBE " + tableName, _conn))
                        {
                            MySqlDataReader reader = mysqlCmd.ExecuteReader();
                            List<string[]> tables = new List<string[]>();
                            int maxStrLen = 0;

                            while (reader.Read())
                            {
                                string tblName = reader.GetString(0);
                                string[] tableSchema = { tblName, reader.GetString(1), reader.GetString(2), reader.GetString(3) };
                                maxStrLen = tblName.Length > maxStrLen ? tblName.Length : maxStrLen;
                                tables.Add(tableSchema);
                            }

                            Console.WriteLine();
                            foreach (string[] tableSchema in tables)
                            {
                                int tblNameLen = tableSchema[0].Length;

                                Console.ForegroundColor = ConsoleColor.Yellow;
                                Console.Write(tableSchema[0]);
                                Console.Write(new String(' ', (maxStrLen - tblNameLen)));
                                Console.ForegroundColor = ConsoleColor.DarkGray;
                                Console.Write("\t[");
                                Console.ForegroundColor = ConsoleColor.Green;
                                Console.Write(tableSchema[1] + ", ");
                                Console.ForegroundColor = ConsoleColor.Magenta;
                                Console.Write(tableSchema[2] + ",");
                                Console.ForegroundColor = ConsoleColor.Cyan;
                                Console.Write(tableSchema[3]);
                                Console.ForegroundColor = ConsoleColor.DarkGray;
                                Console.Write("]");
                                Console.WriteLine();
                            }
                            Console.WriteLine();
                            Console.ForegroundColor = ConsoleColor.Gray;
                            reader.Close();
                        }
                    }
                    catch (Exception e)
                    {
                        WriteError(e.Message);
                    }
                }
                else
                {
                    WriteError("MySql connection is not open. Type help for usage.");
                }
            }
            else
            {
                WriteError("table command requires a table name argument");
            }
        }

        public static void ShowCreateSchema(string[] cmdSegments)
        {
            if (cmdSegments.Length == 2 && cmdSegments[0] == "table")
            {
                string tableName = cmdSegments[1];

                if (tableName == "")
                {
                    WriteError("Table name not specified");
                }
                else
                {

                    if (_conn != null)
                    {
                        try
                        {
                            using (MySqlCommand mysqlCmd = new MySqlCommand("SHOW CREATE TABLE " + tableName, _conn))
                            {
                                MySqlDataReader reader = mysqlCmd.ExecuteReader();
                                reader.Read();
                                SyntaxColorize(reader.GetString(1));
                                reader.Close();
                            }
                        }
                        catch (Exception e)
                        {
                            WriteError(e.Message);
                        }
                    }
                    else
                    {
                        WriteError("MySql connection is not open. Type help for usage.");
                    }
                }
            }
            else
            {
                WriteError("Incorrect show create table syntax.");
            }
        }

        public static void Describe(string[] segments)
        {
            string currentCmd = segments[0];
            segments = segments.Where(x => x != currentCmd).ToArray();

            switch (currentCmd)
            {
                case "table":
                    Table(segments);
                    break;
                default:
                    WriteError(currentCmd + " is not a supported command.");
                    break;
            }
            
        }

        public static void Tables()
        {
            if (_conn != null)
            {
                using (MySqlCommand mysqlCmd = new MySqlCommand("SHOW TABLES", _conn))
                {
                    MySqlDataReader reader = mysqlCmd.ExecuteReader();
                    Console.WriteLine();
                    while (reader.Read())
                    {
                        Console.ForegroundColor = ConsoleColor.Yellow;
                        Console.WriteLine(reader.GetString(0));
                    }
                    Console.WriteLine();
                    Console.ForegroundColor = ConsoleColor.Gray;
                    reader.Close();
                }
            }
            else
            {
                WriteError("MySql connection is not open. Type help for usage.");
            }
        }

        public static void Show(string[] cmdSegments)
        {
            if (cmdSegments.Length > 0)
            {
                string currentCmd = cmdSegments[0];
                cmdSegments = cmdSegments.Where(x => x != currentCmd).ToArray();

                switch (currentCmd)
                {
                    case "tables":
                        Tables();
                        break;

                    case "create":
                        ShowCreateSchema(cmdSegments);
                        break;

                    case "processlist":
                        ProcessList();
                        break;

                    default:
                        WriteError(currentCmd + " is not a supported command.");
                        break;
                }
            }
            else
            {
                WriteError("Too few arguments for command. Type help for usage.");
            }
        }

        public static void ProcessList()
        {
            if (_conn != null)
            {
                using (MySqlCommand mysqlCmd = new MySqlCommand("SHOW PROCESSLIST", _conn))
                {
                    MySqlDataReader reader = mysqlCmd.ExecuteReader();

                    Console.WriteLine();
                    while (reader.Read())
                    {
                        Console.ForegroundColor = ConsoleColor.Yellow;
                        Console.Write(reader.GetValue(0).ToString() + "\t");
                        Console.ForegroundColor = ConsoleColor.Cyan;
                        Console.Write(reader.GetValue(1).ToString() + "\t");
                        Console.ForegroundColor = ConsoleColor.Green;
                        Console.Write(reader.GetValue(2).ToString() + "\t");
                        Console.ForegroundColor = ConsoleColor.White;
                        Console.Write(reader.GetValue(3).ToString() + "\t");
                        Console.ForegroundColor = ConsoleColor.Magenta;
                        Console.WriteLine(reader.GetValue(4).ToString() + "\t");
                    }

                    Console.WriteLine();
                    Console.ForegroundColor = ConsoleColor.Gray;
                    reader.Close();
                }
            }
            else
            {
                WriteError("MySql connection is not open. Type help for usage.");
            }
        }

        public static void Datebase(string[] cmdSegments)
        {
            if (cmdSegments.Length == 1)
            {
                if (_conn != null)
                {
                    string databaseName = cmdSegments[0];

                    try
                    {
                        _conn.ChangeDatabase(databaseName);
                        _database = databaseName;
                        WriteMessage("Database changed to " + databaseName);
                    }
                    catch (Exception e)
                    {
                        WriteError(e.Message);
                    }
                }
                else
                {
                    WriteError("MySql connection is not open. Type help for usage.");
                }
            }
        }

        public static void Disconnect()
        {
            if (_conn != null)
            {
                _conn.Close();
                _conn.Dispose();
                _database = "";
            }
        }

        public static void Connect(string[] cmdSegments)
        {
            if (cmdSegments.Length == 1)
            {
                _connectionString = cmdSegments[0];

                if (_conn != null)
                {
                    _conn.Close();
                    _conn.Dispose();
                }
                try
                {
                    _conn = new MySqlConnection(_connectionString);
                    
                    _conn.Open();
                    _database = _conn.Database;
                    appKey.SetValue("connection_string", _connectionString);

                    if (string.IsNullOrEmpty(_database))
                    {
                        while (true)
                        {
                            Console.Write("> Select database: ");
                            _database = Console.ReadLine();

                            if (_database == ".")
                            {
                                _database = "";
                                break;
                            }

                            try
                            {
                                _conn.ChangeDatabase(_database);
                                WriteMessage("Database changed to " + _database);
                                break;
                            }
                            catch (Exception e)
                            {
                                WriteError(e.Message);
                            }
                        }
                    }
                    
                }
                catch (Exception e)
                {
                    WriteError(e.Message);
                }
            }
            else
            {
                WriteError("Connect command requires a connection string argument");
            }
        }

        public static void Clear()
        {
            Console.Clear();
        }

        public static void Clean()
        {
            Disconnect();
            try
            {
                RegistryKey softwareKey = Registry.CurrentUser.OpenSubKey("Software", true);
                softwareKey.DeleteSubKeyTree("MySqlQueryTool");
            }
            catch (Exception e)
            {
            }
        }

        public static void Help()
        {

            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("connect");
            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine("\t [Connection String]");
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("\t Connect to a MySql databse. e.g connect Server=127.0.0.1;");
            Console.WriteLine();

            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("disconnect");
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("\t Closes an open MySql connection.");
            Console.WriteLine();

            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("db");
            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine("\t [Database Name]");
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("\t Change database.");
            Console.WriteLine();

            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("show");
            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine("\t tables");
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("\t Shows a list of database tables.");
            Console.WriteLine();

            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine("\t create table [Table Name]");
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("\t Shows the SQL statements used to create a specified table.");
            Console.WriteLine();

            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine("\t processlist");
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("\t Shows a list of processes.");
            Console.WriteLine();

            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("describe");
            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine("\t table [Table Name]");
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("\t Shows the tables schema.");
            Console.WriteLine();

            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("export");
            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine("\t [*] [Export file path]");
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("\t Exports all tables to the specified file. File name must not\n\t include any spaces.");
            Console.WriteLine();
            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine("\t [TableName,TableName,TableName...] [Export file path]");
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("\t Exports selected tables to the specified file. TableNames must be \n\t separated by a ',' and not include any spaces. File name must not\n\t include any spaces.");
            Console.WriteLine();

            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine("\t [TableName,TableName,TableName...] [Export file path]");
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("\t Exports selected tables to the specified file. TableNames must be \n\t separated by a ',' and not include any spaces. File name must not\n\t include any spaces.");
            Console.WriteLine();

            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("generate");
            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine("\t entity [Entity Name] [Table Name] [Programming language]");
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("\t Generates a class file to be used as an entity in ORMs.");
            Console.WriteLine();

            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("set");
            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine("\t [Key Name] [Key Value]");
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("\t Sets a value in the system registry which can be \n\t used in with some commands.");
            Console.WriteLine();

            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("get");
            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine("\t [Key Name]");
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("\t Displays the registry value for the specified key. (Factory settings)");
            Console.WriteLine();

            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("clear");
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("\t Clears the console.");
            Console.WriteLine();

            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("clean");
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("\t Closes an open MySql connection and removes registry keys.");
            Console.WriteLine();
        }

        private static string CamelCaseString(string input, bool firstCharUpper = true)
        {
            string[] columnParts = input.Split(new char[] {'_'});
            string camelCasedColumnName = "";

            foreach (string part in columnParts)
            {
                camelCasedColumnName += part[0].ToString().ToUpper() + part.Substring(1);
            }

            if (!firstCharUpper)
            {
                string character = camelCasedColumnName[0].ToString();
                camelCasedColumnName = character.ToLower() + camelCasedColumnName.Substring(1);
            }

            return camelCasedColumnName;
        }

        private static string GetRegValue(string key)
        {
            RegistryKey softwareKey = Registry.CurrentUser.OpenSubKey("Software", true);
            appKey = softwareKey.OpenSubKey("MySqlQueryTool", true);

            if (appKey != null)
            {
                return appKey.GetValue(key).ToString();
            }
            return "";
        }

        private static string[] ParseCommand(string cmd)
        {
            string[] segments = cmd.Split(new char[] { ' ' });
            return segments;
        }

        private static void WriteError(string message)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine(message);
            Console.ForegroundColor = ConsoleColor.Gray;
        }

        private static void WriteMessage(string message)
        {
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine(message);
            Console.ForegroundColor = ConsoleColor.Gray;
        }

        private static void PrintSplash()
        {
            Console.Title = "MySql Tool";

            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine("   MySQL");
            Console.ForegroundColor = ConsoleColor.Gray;
            Console.WriteLine();
            Console.WriteLine("   ######  ####   ####   #");
            Console.WriteLine("     ##   #    # #    #  #");
            Console.WriteLine("     ##   #    # #    #  #");
            Console.WriteLine("     ##   #    # #    #  #");
            Console.WriteLine("     ##    ####   ####   #####");
            Console.WriteLine();
        }

        private static void SyntaxColorize(string sql)
        {
            Console.WriteLine();
            int length = sql.Length;

            string token = "";
            bool backTickOpen = false;
            bool backTickColorize = false;

            for (int i = 0; i < length; i++)
            {
                char ch = sql[i];

                if (ch == '`')
                {
                    backTickOpen = backTickOpen ? false : true;

                    if (backTickOpen == false)
                    {
                        backTickColorize = true;
                    }
                }

                if(backTickOpen == false){
                    string[] keywords = { "CREATE", "TABLE", "PRIMARY", "KEY", "UNIQUE", "ENGINE", "AUTO_INCREMENT", "DEFAULT",  "CHARSET", "COLLATE", "NOT", "NULL", "unsigned" };

                    if (keywords.Contains(token.Trim()))
                    { 
                        Console.ForegroundColor = ConsoleColor.Cyan;
                        Console.Write(token + " ");
                        Console.ForegroundColor = ConsoleColor.Gray;
                        token = "";
                        continue;
                    }
                }

                if (ch == ' ' && backTickOpen == false)
                {
                    if (backTickColorize)
                    {
                        Console.ForegroundColor = ConsoleColor.Yellow;
                        backTickColorize = false;
                    }

                    Console.Write(token);
                    Console.ForegroundColor = ConsoleColor.Gray;
                    token = "";
                }

                token += ch.ToString();
            }
            Console.WriteLine(token);
            Console.WriteLine();
        }
    }
}
